//////////////////////////////////////////////////////////////////////////////////
//	Copyright 2011 by Yosef Grabivker, ryuho@homenetworksoft.com
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//////////////////////////////////////////////////////////////////////////////////

#include <wx/wx.h>
#include <wx/statline.h>
#include <wx/textctrl.h>
#include "configdata.h"
#include "generaloptions.h"
#include "advancedoptdlg.h"
#include "listselector.h"

typedef struct tagLang
{
	int			id;
	wxString	name;
}LANG;

static LANG lang[]=
{
	{wxLANGUAGE_DEFAULT,	_("OS Default")},
	{wxLANGUAGE_ENGLISH,	_("English")	},
	//{wxLANGUAGE_FRENCH,	_("French")	},			
	//{wxLANGUAGE_GERMAN,	_("German")	},
	{wxLANGUAGE_RUSSIAN,	_("Russian")	}
};

enum cDialogID
{
	cComboIDLang=12000,
	cCBNatOptID,
	cCBP2POptID,
	cCBTCPOptID,
	cCBICMPOptID,
	cCBAdvancedOptID,
	cBtnAdvancedID,
	cIDEnableSSCRPT,
	cIDBrowseButton,
	cCBWWWOptID,
	cIDUnloadProcButton,
	cIDUnloadModButton,
};

BEGIN_EVENT_TABLE(CGeneralOptions, wxPanel)
	EVT_TEXT(cComboIDLang, 	CGeneralOptions::OnLangChanged)
	EVT_COMMAND_RANGE(cCBNatOptID, cCBICMPOptID, wxEVT_COMMAND_CHECKBOX_CLICKED, CGeneralOptions::OnOptimzCheckBoxes)
	EVT_CHECKBOX(cCBAdvancedOptID, CGeneralOptions::OnOptimzAdvancedCheckBox)
	EVT_BUTTON(cBtnAdvancedID, CGeneralOptions::OnAdvanced)
	EVT_BUTTON(cIDBrowseButton, CGeneralOptions::OnSelectStartUpScriptFileName)
	EVT_CHECKBOX(cIDEnableSSCRPT, CGeneralOptions::OnTogleStartUpScript)
	EVT_BUTTON(cIDUnloadProcButton, CGeneralOptions::OnSelectProcList)
	EVT_BUTTON(cIDUnloadModButton, CGeneralOptions::OnSelectModList)
	EVT_UPDATE_UI(cIDUnloadProcButton, CGeneralOptions::OnUnloadProcButtonUI)
	EVT_UPDATE_UI(cIDUnloadModButton, CGeneralOptions::OnUnloadModButtonUI)
END_EVENT_TABLE()

CGeneralOptions::CGeneralOptions(wxWindow* pParent):wxPanel(pParent, wxID_ANY), m_langid(wxLANGUAGE_ENGLISH) 
{
	wxFlexGridSizer* pSizer = new wxFlexGridSizer(2, 2, 5, 5);

	//Startup
	wxStaticBoxSizer* pStartUpBox = new wxStaticBoxSizer( new
		wxStaticBox(this, wxID_ANY,  _("Startup")), wxVERTICAL);

	#ifndef LINUX
	m_pBootRun = new wxCheckBox(this, wxID_ANY, _("Start on system startup") );
	pStartUpBox->Add(m_pBootRun, 1, wxALL|wxEXPAND|wxALIGN_CENTER, 5);
	#endif

	m_pCheckForUpd = new wxCheckBox(this, wxID_ANY, _("Check for updates") );
	pStartUpBox->Add(m_pCheckForUpd, 1, wxALL|wxEXPAND|wxALIGN_CENTER, 5);
	

	pSizer->Add( pStartUpBox, 1, wxALL|wxEXPAND, 5 );

	//Language
	wxStaticBoxSizer* pLangBox = new wxStaticBoxSizer( new
		wxStaticBox(this, wxID_ANY,  _("Language")), wxHORIZONTAL);

	//wxStaticText* pTxt = new wxStaticText(this, wxID_ANY, _("Language"));
	m_pcLanguage = new wxComboBox(this, cComboIDLang,  lang[0].name , wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN|wxCB_READONLY  );
	
	InitLangCombo();

	//pLangBox->Add(pTxt, 1, wxALL|wxEXPAND|wxALIGN_CENTER, 5);
	pLangBox->Add(m_pcLanguage, 0, wxALL|wxALIGN_CENTER, 5);

	pSizer->Add( pLangBox, 1, wxALL|wxEXPAND, 5 );


	//Optimization
	wxStaticBoxSizer* pOptBox = new wxStaticBoxSizer( new
		wxStaticBox(this, wxID_ANY,  _("Optimization")), wxVERTICAL);

	m_pcbNatSizeOpt = new wxCheckBox(this, wxID_ANY,	_("NAT table size") );
	m_pcbNatOpt = new wxCheckBox(this, cCBNatOptID,		_("NAT settings") );
	m_pcbTCPOpt = new wxCheckBox(this, cCBTCPOptID,		_("TCP") );
	m_pcbICMPOpt = new wxCheckBox(this, cCBICMPOptID,	_("ICMP") );

	wxRadioButton* pNone = new wxRadioButton(this, -1, _("Disabled") );
	pNone->SetValue(true);

	wxStaticLine* pLine = new wxStaticLine(this, -1 );

	m_pcbPeerToPeerOpt = new wxRadioButton(this, cCBP2POptID, _("P2P networks") );
	m_pcbWWWOpt = new wxRadioButton(this, cCBWWWOptID, _("WWW/FTP") );
	
	wxBoxSizer* pLineSz = new wxBoxSizer(wxHORIZONTAL);
	m_pcbAdvanced = new wxRadioButton(this, cCBAdvancedOptID, wxT("") );
	wxButton* m_pAdvanced = new wxButton(this, cBtnAdvancedID, _("Custom"));
	pLineSz->Add(m_pcbAdvanced,0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 20);
	pLineSz->Add(m_pAdvanced,0, wxALIGN_CENTER_VERTICAL, 0);

	m_pcbAdvanced->Enable(false);
	m_pAdvanced->Enable(false);
	

	pOptBox->Add(m_pcbNatSizeOpt, 1, wxALL|wxEXPAND|wxALIGN_CENTER, 5);
	pOptBox->Add(m_pcbNatOpt, 1, wxALL|wxEXPAND|wxALIGN_CENTER, 5);
	pOptBox->Add(m_pcbTCPOpt, 1, wxALL|wxEXPAND|wxALIGN_CENTER, 5);
	pOptBox->Add(m_pcbICMPOpt, 1, wxALL|wxEXPAND|wxALIGN_CENTER, 5);

	
	pOptBox->Add(pLine, 0, wxALL|wxEXPAND|wxALIGN_CENTER, 5);
	pOptBox->Add(pNone, 1, wxALL|wxEXPAND|wxALIGN_CENTER, 5);
	pOptBox->Add(m_pcbPeerToPeerOpt, 1, wxALL|wxEXPAND|wxALIGN_CENTER, 5);
	pOptBox->Add(m_pcbWWWOpt, 1, wxALL|wxEXPAND|wxALIGN_CENTER, 5);

	pOptBox->Add(pLineSz, 0 , wxALL|wxEXPAND|wxALIGN_CENTER, 5);

	pSizer->Add( pOptBox, 1, wxALL|wxEXPAND, 5 );

	//-->sizer for other options
	wxBoxSizer* pOtherSz = new wxBoxSizer(wxVERTICAL);

	////////////////////////////////////////////////////////////////////////
	//Start up script
	int nFlags  = wxALL|wxALIGN_CENTER;
	int nBorder = 5;

	m_pSSCRPTBox = new wxStaticBoxSizer( new
		wxStaticBox(this, wxID_ANY,  _("Router Startup Script")), wxHORIZONTAL);

	m_pcbEnableSSCRPT = new wxCheckBox(this, cIDEnableSSCRPT, wxT(""));
	m_pSSCRPTBox->Add(m_pcbEnableSSCRPT, 0, nFlags, nBorder );

	m_ptcDirName = new wxTextCtrl(this, wxID_ANY,wxT(""), wxDefaultPosition, wxSize(100, wxDefaultSize.GetY()));
	m_pSSCRPTBox->Add(m_ptcDirName, 0, nFlags, nBorder);

	wxButton* pBtn = new wxButton(this, cIDBrowseButton, wxT("..."), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT|wxNO_BORDER );
	m_pSSCRPTBox->Add(pBtn, 0, nFlags, nBorder);

	pOtherSz->Add( m_pSSCRPTBox, 0, wxALL|wxEXPAND, 5 );

	m_pcbEnableSSCRPT->Enable(false);
	m_ptcDirName->Enable(false);
	pBtn->Enable(false);

	////////////////////////////////////////////////////////////////////////
	

	////////////////////////////////////////////////////////////////////////
	//Memory

	//wxHORIZONTAL
	wxStaticBoxSizer* pMemoryBox = new wxStaticBoxSizer( new
		wxStaticBox(this, wxID_ANY,  _("Memory")), wxVERTICAL);


	wxFlexGridSizer *pMem = new wxFlexGridSizer(2, 2, nBorder, nBorder);

	{
		m_pcbEnableKillProc = new wxCheckBox(this, wxID_ANY, wxT("Unload unused programs"));
		pMem->Add(m_pcbEnableKillProc, 0, wxALL, nBorder );

		wxButton* pBtnUnload = new wxButton(this, cIDUnloadProcButton, wxT("..."), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT|wxNO_BORDER );
		pMem->Add(pBtnUnload, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 0);

		m_pcbEnableKillProc->Enable(false);
		pBtnUnload->Enable(false);
	}

	{
		m_pcbEnableUnloadMod = new wxCheckBox(this, wxID_ANY, wxT("Unload unused kernel modules"));
		pMem->Add(m_pcbEnableUnloadMod, 0, wxALL, nBorder );

		wxButton* pBtnUnload = new wxButton(this, cIDUnloadModButton, wxT("..."), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT|wxNO_BORDER );
		pMem->Add(pBtnUnload, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 0);

		m_pcbEnableUnloadMod->Enable(false);
		pBtnUnload->Enable(false);
	}

	pMemoryBox->Add( pMem );
	pOtherSz->Add( pMemoryBox, 0, wxALL|wxEXPAND, 5 );
	////////////////////////////////////////////////////////////////////////


	pSizer->Add( pOtherSz, 1, wxEXPAND, 0 );
	SetSizer( pSizer );
}

CGeneralOptions::~CGeneralOptions(void)
{
}

void CGeneralOptions::InitLangCombo()
{
	for ( size_t i=0;i<sizeof(lang)/sizeof(lang[0]);i++ )
	{
		LANG& cur = lang[i];

		if ( wxLocale::IsAvailable(cur.id) )
		{
			m_pcLanguage->Append(cur.name, (void*)cur.id);
		}
	}
}

void CGeneralOptions::SelectLang(long lang)
{
	void* pData;
	
	for ( size_t i=0;i<m_pcLanguage->GetCount();i++ )
	{
		pData = m_pcLanguage->GetClientData( i );
		
		if ( lang == (long)pData )
		{
			m_pcLanguage->SetSelection( i );
			return;
		}
	}

	m_pcLanguage->SetSelection( 0 );
}

void CGeneralOptions::OnLangChanged(wxCommandEvent&)
{
	void* pData = m_pcLanguage->GetClientData( m_pcLanguage->GetCurrentSelection());
	m_langid = (long)pData;
	
	/*
	wxLocale locale;
	if ( !locale.Init( m_langid, wxLOCALE_CONV_ENCODING) )
	{
		wxLogError(_("Selected language is not supported by the system."));
		m_langid = wxLANGUAGE_ENGLISH;
		//SelectLang(m_langid);
	}*/
}

void CGeneralOptions::OnOptimzCheckBoxes(wxCommandEvent& ev)
{
	//m_pcbAdvanced
	bool bVal =	m_pcbNatOpt->GetValue();
	bVal|=m_pcbPeerToPeerOpt->GetValue();
	bVal|=m_pcbTCPOpt->GetValue();
	bVal|=m_pcbICMPOpt->GetValue();

	if ( bVal )
	{
		m_pcbAdvanced->SetValue(false);
	}
}

void CGeneralOptions::OnOptimzAdvancedCheckBox(wxCommandEvent& ev)
{
	if ( m_pcbAdvanced->GetValue() )
	{
		m_pcbNatOpt->SetValue(false);
		m_pcbPeerToPeerOpt->SetValue(false);
		m_pcbTCPOpt->SetValue(false);
		m_pcbICMPOpt->SetValue(false);
	}
}

void CGeneralOptions::OnAdvanced(wxCommandEvent& ev)
{
	CAdvancedOptDlg dlg(this);

	dlg.Load( m_lstAdvancedOpt );

    if ( dlg.ShowModal() == wxID_OK )
	{
		m_pcbAdvanced->SetValue(true);
		
		wxCommandEvent ev(1); 
		OnOptimzAdvancedCheckBox( ev );

		m_lstAdvancedOpt = dlg.Save();
	}
}

void CGeneralOptions::OnSelectStartUpScriptFileName(wxCommandEvent& event)
{
	try
	{
		wxFileDialog dlg(this, _("Choose a file"),
				wxT(""), wxT("startupscript.sh"), wxT("*.*"), wxFD_OPEN|wxFD_FILE_MUST_EXIST );

		if ( wxID_OK ==dlg.ShowModal() )
		{
			m_ptcDirName->SetValue(dlg.GetPath());
		}
	}
	catch(...)
	{
		wxMessageBox(_("Failed!"), _("Error"), wxICON_WARNING | wxOK, this);
	}
}

void CGeneralOptions::OnTogleStartUpScript(wxCommandEvent& event)
{
	wxSizerItemList list = m_pSSCRPTBox->GetChildren();

	wxSizerItemList::iterator iter;
    for (iter = list.begin(); iter != list.end(); ++iter)
    {
       wxSizerItem *pItem = *iter;

	   if ( pItem && pItem->GetWindow()!=m_pcbEnableSSCRPT )
	   {
		   pItem->GetWindow()->Enable(m_pcbEnableSSCRPT->GetValue());
	   }
	}
}

void CGeneralOptions::OnUnloadProcButtonUI(wxUpdateUIEvent& event)
{
	event.Enable( m_pcbEnableKillProc->IsChecked() );
}

void CGeneralOptions::OnSelectProcList(wxCommandEvent& event)
{
	CListSelector dlgList(m_lstKillProc, _("Unused programs list"));

	if ( wxID_OK == dlgList.ShowModal() )
	{
		m_lstKillProc = dlgList.GetList();
	}
}

void CGeneralOptions::OnUnloadModButtonUI(wxUpdateUIEvent& event)
{
	event.Enable( m_pcbEnableUnloadMod->IsChecked() );
}

void CGeneralOptions::OnSelectModList(wxCommandEvent& event)
{
	CListSelector dlgList(m_lstUnloadMod, _("Unused kernel modules list"));

	if ( wxID_OK == dlgList.ShowModal() )
	{
		m_lstUnloadMod = dlgList.GetList();
	}
}

//////////////////////////////////////////////////////////////////////////////
//Run at startup
bool CGeneralOptions::GetBootRun()
{
	#ifndef LINUX
	return m_pBootRun->GetValue();
	#else
	return false;
	#endif
}

void CGeneralOptions::SetBootRun(bool bVal)
{
	#ifndef LINUX
	m_pBootRun->SetValue( bVal );
	#endif
}

bool CGeneralOptions::GetUpdCheck()
{
	return m_pCheckForUpd->GetValue();
}

void CGeneralOptions::SetUpdCheck(bool bVal)
{
	m_pCheckForUpd->SetValue( bVal );
}




//NAT Optimization
bool CGeneralOptions::GetEnableNATOpt()
{
	return m_pcbNatOpt->GetValue();
}

void CGeneralOptions::SetEnableNATOpt(bool bVal)
{
	m_pcbNatOpt->SetValue(bVal);
}

//NAT Size Optimization
bool CGeneralOptions::GetEnableNATSizeOpt()
{
	return m_pcbNatSizeOpt->GetValue();
}

void CGeneralOptions::SetEnableNATSizeOpt(bool bVal)
{
	m_pcbNatSizeOpt->SetValue(bVal);
}

//Peer To Peer
bool CGeneralOptions::GetEnableP2PNetworkOpt()
{
	return m_pcbPeerToPeerOpt->GetValue();
}

void CGeneralOptions::SetEnableP2PNetworkOpt(bool bVal)
{
	m_pcbPeerToPeerOpt->SetValue( bVal );
}

//WWW
bool CGeneralOptions::GetEnableWWWOpt()
{
	return m_pcbWWWOpt->GetValue();
}

void CGeneralOptions::SetEnableWWWOpt(bool bVal/*=true*/)
{
	m_pcbWWWOpt->SetValue( bVal );
}


long CGeneralOptions::GetLanguage()
{
	return m_langid;
}

void CGeneralOptions::SetLanguage(long lVal)
{
	m_langid = lVal;
	
	if ( wxLocale::IsAvailable(m_langid) )
	{
		SelectLang(lVal);
	}
	else
	{
		m_langid = wxLANGUAGE_DEFAULT;
		SelectLang(m_langid);
	}
}

//TCP
bool CGeneralOptions::GetEnableTCPOpt()
{
	return m_pcbTCPOpt->GetValue();
}

void CGeneralOptions::SetEnableTCPOpt(bool bVal)
{
	m_pcbTCPOpt->SetValue( bVal );
}

//icmp
bool CGeneralOptions::GetEnableICMPOpt()
{
	return m_pcbICMPOpt->GetValue();
}

void CGeneralOptions::SetEnableICMPOpt(bool bVal)
{
	m_pcbICMPOpt->SetValue( bVal );
}

//advanced
bool CGeneralOptions::GetEnableAdvancedOpt()
{
	return m_pcbAdvanced->GetValue();
}

void CGeneralOptions::SetEnableAdvancedOpt(bool bVal)
{
	m_pcbAdvanced->SetValue( bVal ); 
}

//Start up script
void CGeneralOptions::SetEnableStartUpScript( bool bSet )
{
	m_pcbEnableSSCRPT->SetValue(bSet);
	wxCommandEvent event;
	OnTogleStartUpScript(event);
}

bool CGeneralOptions::GetEnableStartUpScript()
{
	return m_pcbEnableSSCRPT->GetValue();
}

void CGeneralOptions::SetStartUpScriptFileName( const wxString& str )
{
	m_ptcDirName->SetValue(str);
}

wxString CGeneralOptions::GetStartUpScriptFileName()
{
	return m_ptcDirName->GetValue();
}

//Proc Kill
void CGeneralOptions::SetEnableProcKill( bool bSet )
{
	m_pcbEnableKillProc->SetValue( bSet );
}

bool CGeneralOptions::GetEnableProcKill()
{
	return m_pcbEnableKillProc->GetValue();
}

//Mod Unload
void CGeneralOptions::SetEnableModUnload( bool bSet )
{
	m_pcbEnableUnloadMod->SetValue( bSet );
}

bool CGeneralOptions::GetEnableModUnload()
{
	return m_pcbEnableUnloadMod->GetValue();
}

